<script lang="ts">
	import Scrollbar from '$lib/components/Basic/Scrollbar/Scrollbar.svelte';
	import {
		tableContextKey,
		type TableContext,
		type ColumnConfig,
		type HeaderCell,
		type SummaryType,
		type SummaryCell
	} from './context/table-context';
	import { setContext, onMount, onDestroy, tick } from 'svelte';
	import { throttle, debounce } from 'lodash-es';
	import { type SortDirection } from './context/table-context';
	import {
		createComparator,
		isValueEqual,
		getHeaderTree,
		getLeafColumns,
		getLeafKeys,
		calculateAggregate,
		generateSummaryCells
	} from './utils/common';
	import VirtualScroll from '$lib/components/Basic/VirtualScroll/VirtualScroll.svelte';
	import Icon from '$lib/components/Basic/Icon/Icon.svelte';
	import LoadingBar from '$lib/components/ExceptionPage/LoadingBar.svelte';
	import PopoverSlot from '$lib/components/Basic/Popover/PopoverSlot.svelte';
	import Portal from 'svelte-portal';
	import { ensurePortalContainer } from '$lib/utils/container/ensurePortalContainer';
	import { getElementRelativePos } from '$lib/utils/position/getElementPos';
	import Input from '$lib/components/Form/Input/Input.svelte';
	import RectButton from '$lib/components/Basic/Button/RectButton.svelte';
	import Checkbox from '$lib/components/Form/Checkbox/Checkbox.svelte';
	import CheckboxGroup from '$lib/components/Form/Checkbox/CheckboxGroup.svelte';
	import CheckboxSelectAll from '$lib/components/Form/Checkbox/CheckboxSelectAll.svelte';
	import Divider from '$lib/components/Basic/Divider/Divider.svelte';
	import Badge from '$lib/components/Data/Badge/Badge.svelte';
	import { cloneDeep } from 'lodash-es';
	import CheckSquare from '$lib/components/Form/Checkbox/CheckSquare.svelte';

	/** 主组件属性类型（新增表头高度入参） */
	interface TableProps<T = Record<string, any>> {
		data: T[];
		isLoading?: boolean;
		theadClass?: string;
		tbodyClass?: string;
		rowClass?: (row: T, index: number) => string;
		stripe?: boolean;
		border?: boolean;
		size?: 'sm' | 'md' | 'lg';
		showSummary?: boolean; // 是否显示合计行
		summaryMethod?: (params: { columns: ColumnConfig[]; data: T[] }) => Record<string, any>; // 全局自定义合计
		children?: any;
		// 新增：排序相关属性
		onSortChange?: (sortState: { key: string; direction: SortDirection }[]) => void;
		// 新增：筛选相关属性
		onFilterChange?: (
			column: string,
			value: string | number | (string | number)[] | null | undefined
		) => void;
		// 新增：虚拟滚动配置
		virtualized?: boolean;
		rowHeight?: number;
		//新增Multiple选择
		multiple?: boolean;
	}

	// 主组件 props 获取
	const {
		data = [],
		isLoading = false,
		theadClass = '',
		tbodyClass = '',
		rowClass = () => '',
		stripe = false,
		border = false,
		size = 'md',
		showSummary = false,
		summaryMethod: globalSummaryMethod, // 别名避免冲突
		children,
		onSortChange,
		onFilterChange,
		// 虚拟滚动相关属性
		virtualized = false,
		rowHeight, // 默认行高
		multiple = false
	}: TableProps = $props();

	const rowHeightMap = { sm: 30, md: 34, lg: 40 };
	let loadingVisible = $state(false);

	/** 响应式存储列配置和列宽 */
	const rootColumns = $state<ColumnConfig[]>([]);
	let columnWidths = $state<Record<string, string>>({});
	let tableContainerRef: HTMLElement | undefined = undefined; // 弹出框引用
	let totalWidth: number = $state(0);

	/** 实现上下文方法：添加列 */
	const addColumn = (config: ColumnConfig) => {
		if (!rootColumns.some((col) => col.key === config.key)) {
			rootColumns.push(config);
		}
	};

	/** 实现上下文方法：移除列 */
	const removeColumn = (key: ColumnConfig['key']) => {
		const index = rootColumns.findIndex((col) => col.key === key);
		if (index !== -1) {
			rootColumns.splice(index, 1);
			delete columnWidths[key as string];
			// 清理排序和筛选状态
			sortState = sortState.filter((item) => item.key !== key);
			if (optionFilterState[key as string] !== undefined) {
				delete optionFilterState[key as string];
			}
			if (keywordFilterState[key as string] !== undefined) {
				delete keywordFilterState[key as string];
			}
			if (customFilterState[key as string] !== undefined) {
				delete customFilterState[key as string];
			}
		}
	};
	// --- 衍生状态 ---
	let headerTree = $state<HeaderCell[]>([]);
	let columns = $state<ColumnConfig[]>([]);
	let maxHeaderDepth = $state(1);
	$effect(() => {
		columns = getLeafColumns(rootColumns); // 扁平化的叶子列（用于表体）
		const { cols, maxDepth } = getHeaderTree(rootColumns); // 表头行数据
		headerTree = cols;
		maxHeaderDepth = maxDepth;
	});

	// 辅助：获取某列的显示宽度（像素数值）
	const getColWidthVal = (key: string) => {
		const w = columnWidths[key];
		return w ? parseFloat(w) : 0;
	};

	// 辅助：计算分组表头的总宽度
	const getGroupWidth = (col: ColumnConfig) => {
		const keys = getLeafKeys(col);
		// 使用 getColWidthVal 获取实时宽度
		const total = keys.reduce((sum, key) => {
			const wStr = columnWidths[key];
			const w = wStr ? parseFloat(wStr) : 0;
			return sum + w;
		}, 0);
		return total;
	};

	// 新增：表体滚动位置，用于同步表头
	let tbodyScrollLeft = $state(0);

	// 记忆化列宽计算结果
	let lastColumnsState = '';
	let columnTotalWidths: number = $state(0);
	let tableContainerHeight: number = $state(0);

	// 优化的列宽计算函数
	const handleResize = throttle(() => {
		if (!tableContainerRef) return;

		const containerWidth = tableContainerRef.offsetWidth - (multiple ? 30 : 0) - (border ? 2 : 0);
		tableContainerHeight = tableContainerRef.offsetHeight;

		// 性能优化：使用更高效的缓存策略
		const currentColumnsState = columns
			.map((col) => col.key + ':' + col.width + ':' + col.minWidth)
			.join('|');
		if (currentColumnsState === lastColumnsState && containerWidth === totalWidth) {
			return;
		}
		columnTotalWidths = 0;

		// 更新缓存状态
		lastColumnsState = currentColumnsState;
		totalWidth = containerWidth;

		// 使用Map预分配，减少对象属性访问次数
		const newColumnWidths = new Map<string, number>();

		// 区分固定列（有width）和弹性列（无width但有minWidth）
		const fixedColumns = columns.filter((col) => col.width > 0);
		const flexWithMinColumns = columns.filter((col) => col.width <= 0 && col.minWidth > 0);
		const noConfigColumns = columns.filter((col) => col.width <= 0 && col.minWidth <= 0);

		// 计算固定列总宽度
		const fixedTotal = fixedColumns.reduce((sum, col) => sum + col.width, 0);
		// 计算弹性列的总最小宽度
		const flexMinTotal = flexWithMinColumns.reduce((sum, col) => sum + col.minWidth, 0);
		const requiredTotal = fixedTotal + flexMinTotal;

		// 剩余可分配空间 = 容器总宽 - 固定列总宽
		const remainingSpace = Math.max(0, totalWidth - requiredTotal);

		// 1. 处理固定列：直接使用设定的width
		for (const col of fixedColumns) {
			newColumnWidths.set(col.key as string, col.width);
		}
		// 2. 处理弹性列：按minWidth比例分配剩余空间
		if (flexWithMinColumns.length > 0) {
			if (remainingSpace <= 0 || noConfigColumns.length > 0) {
				// 空间不足：仅保留minWidth
				for (const col of flexWithMinColumns) {
					newColumnWidths.set(col.key as string, col.minWidth);
				}
			} else {
				// 空间充足：多余空间按minWidth比例分配
				const extraSpace = remainingSpace;
				// 只计算一次总和
				const totalFlexMin = flexMinTotal; // 复用上面计算的结果
				for (const col of flexWithMinColumns) {
					const proportion = col.minWidth / totalFlexMin;
					const finalWidth = Math.floor(col.minWidth + extraSpace * proportion);
					newColumnWidths.set(col.key as string, finalWidth);
				}
			}
		}

		// 3. 处理无配置列：均分剩余空间（无其他列时占满容器）
		if (noConfigColumns.length > 0) {
			// 无配置列最小宽度默认50px（避免过窄）
			const minNoConfigWidth = 70;
			const totalNoConfigMin = noConfigColumns.length * minNoConfigWidth;

			if (remainingSpace <= totalNoConfigMin) {
				// 剩余空间不足：每列按最小宽度分配
				for (const col of noConfigColumns) {
					newColumnWidths.set(col.key as string, minNoConfigWidth);
				}
			} else {
				// 剩余空间充足：均分剩余空间
				const perNoConfigWidth = Math.floor(remainingSpace / noConfigColumns.length);
				for (const col of noConfigColumns) {
					newColumnWidths.set(col.key as string, perNoConfigWidth);
				}
			}
		}

		// 批量更新columnWidths，减少响应式更新次数
		// 创建新对象而不是直接修改，确保响应式更新正确触发
		const updatedWidths: Record<string, string> = {};
		newColumnWidths.forEach((value, key) => {
			updatedWidths[key] = `${value}px`;
			columnTotalWidths += value;
		});
		columnWidths = updatedWidths;
	}, 30); // 增加节流时间，减少高频调整时的计算

	let headerScrollContainer: HTMLElement;
	let footerScrollContainer: HTMLElement | null = $state(null);
	// source: 触发滚动的来源
	const handleScrollSync = (scrollLeft: number, source: 'body' | 'footer') => {
		// 简单的防抖/防循环：如果位置没变，不处理
		// if (Math.abs(tbodyScrollLeft - scrollLeft) < 1) return;

		tbodyScrollLeft = scrollLeft;

		// 1. 同步 Header (总是需要)
		if (headerScrollContainer) {
			headerScrollContainer.scrollLeft = scrollLeft;
		}

		// 2. 同步 另一方
		if (source === 'body') {
			// Body 动了 -> 同步 Footer
			if (footerScrollContainer instanceof HTMLElement) footerScrollContainer.scrollLeft = scrollLeft;
		} else {
			// Footer 动了 -> 同步 Body (通过绑定的 ref)
			if (scrollContainerRef instanceof HTMLElement) scrollContainerRef.scrollLeft = scrollLeft;
		}
	};
	// Body 滚动回调 (传递给 VirtualScroll/Scrollbar)
	const handleTbodyScroll = ({
		scrollTop,
		scrollLeft
	}: {
		scrollTop: number;
		scrollLeft: number;
	}) => {
		// 纵向滚动不需要同步给 Footer，Footer 是固定底部的
		handleScrollSync(scrollLeft, 'body');
	};

	// 新增：排序状态管理
	let sortState = $state<{ key: string; direction: SortDirection }[]>([]);

	/** 实现上下文方法：排序 */
	// const sort = (key: ColumnConfig['key'], direction: SortDirection) => {
	// 	sortState.key = key;
	// 	sortState.direction = direction;
	// 	processData(data, false);
	// 	// 调用外部回调
	// 	if (onSortChange) {
	// 		onSortChange(key as string, direction);
	// 	}
	// };

	/** 处理排序点击 */
	const handleSortClick = (e: MouseEvent, col: ColumnConfig) => {
		if (!col.sortable) return;
		const key = col.key as string;
		const isMultiSort = e.ctrlKey || e.metaKey;
		// 查找当前列是否已在排序列表中
		const existingIndex = sortState.findIndex((item) => item.key === key);

		if (isMultiSort) {
			// --- 多列排序模式 (追加/修改) ---
			if (existingIndex > -1) {
				// 如果已存在，切换方向: ascend -> descend -> remove
				const currentDir = sortState[existingIndex].direction;
				if (currentDir === 'ascend') {
					sortState[existingIndex].direction = 'descend';
				} else {
					// 再次点击降序，移除该列排序
					sortState.splice(existingIndex, 1);
				}
			} else {
				// 如果不存在，追加到末尾
				sortState.push({ key, direction: 'ascend' });
			}
		} else {
			// --- 单列排序模式 (替换) ---
			if (existingIndex > -1 && sortState.length === 1) {
				// 如果当前只有这一列在排序，且点击的是它，则循环方向
				const currentDir = sortState[0].direction;
				if (currentDir === 'ascend') {
					sortState[0].direction = 'descend';
				} else {
					sortState = []; // 清空
				}
			} else {
				// 否则，清空其他所有排序，只保留当前列
				sortState = [{ key, direction: 'ascend' }];
			}
		}
		processData(data, false);
		if (onSortChange && sortState.length > 0) {
			onSortChange(sortState);
		}
	};

	// 新增：筛选状态
	let portalContainer: HTMLElement | undefined = $state(undefined);
	let popoverSlotRefs: Record<string, HTMLElement | undefined> = $state({});
	let triggerRefs: Record<string, HTMLElement | undefined> = $state({});
	let triggerRects: Record<
		string,
		{
			top: number;
			left: number;
			bottom: number;
			right: number;
			width: number;
			height: number;
		}
	> = {};
	const optionFilterState = $state<Record<string, (string | number)[]>>({});
	const keywordFilterState = $state<Record<string, (string | number)[]>>({});
	// 🔥 新增：专门存储自定义筛选的值 (例如 {min: 10, max: 20})
	const customFilterState = $state<Record<string, any>>({});
	// 新增：筛选下拉框显示状态
	let filterDropdownVisible = $state<ColumnConfig['key'] | null>(null);
	// 新增：临时筛选值（用于筛选下拉框的精确匹配）
	const tempOptionFilters = $state<Record<string, (string | number)[]>>({});
	// 新增：临时关键字筛选值（用于模糊匹配）
	const tempKeywordFilters = $state<Record<string, (string | number)[]>>({});

	// 新增：筛选选项类型
	interface FilterOption {
		label: string;
		value: any;
	}

	// 新增：筛选选项缓存
	const filterOptionsCache = $state<Record<string, FilterOption[]>>({});
	// 新增：筛选选项加载状态
	const filterOptionsLoading = $state<Record<string, boolean>>({});
	// 新增：表格最大数量限制
	const MAX_FILTER_OPTIONS = 1000;

	/** 实现上下文方法：筛选 */
	const filter = (
		key: ColumnConfig['key'],
		value: any,
		valueType: 'option' | 'string' | 'customize' | 'delete'
	) => {
		const keyStr = String(key);
		if (valueType === 'delete') {
			delete optionFilterState[keyStr];
			delete keywordFilterState[keyStr];
			delete customFilterState[keyStr];
			processData(data, false);
			return;
		}
		if (valueType === 'option') {
			delete keywordFilterState[keyStr];
			delete customFilterState[keyStr];
			const oldValue = optionFilterState[keyStr];
			// 核心：一致性判断 - 新旧值一致则直接返回，不执行后续操作
			if (isValueEqual(oldValue, value)) {
				return;
			}

			// 如果值为undefined或null，则删除该筛选条件
			if (value === undefined || value === null || (Array.isArray(value) && value.length === 0)) {
				delete optionFilterState[keyStr];
			} else {
				optionFilterState[keyStr] = value;
			}
			processData(data, false);
		} else if (valueType === 'string') {
			delete optionFilterState[keyStr];
			delete customFilterState[keyStr];
			const oldValue = keywordFilterState[keyStr];
			// 核心：一致性判断 - 新旧值一致则直接返回，不执行后续操作
			if (isValueEqual(oldValue, value)) {
				return;
			}

			// 如果值为undefined或null，则删除该筛选条件
			if (value === undefined || value === null || (Array.isArray(value) && value.length === 0)) {
				delete keywordFilterState[keyStr];
			} else {
				keywordFilterState[keyStr] = value;
			}
			processData(data, false);
		} else if (valueType === 'customize') {
			delete optionFilterState[keyStr];
			delete keywordFilterState[keyStr];
			const oldValue = customFilterState[keyStr];
			// 核心：一致性判断 - 新旧值一致则直接返回，不执行后续操作
			if (isValueEqual(oldValue, value)) {
				return;
			}
			// 如果值为undefined或null，则删除该筛选条件
			if (value === undefined || value === null || value === '') {
				delete customFilterState[keyStr];
			} else {
				customFilterState[keyStr] = value;
			}
			processData(data, false);
		}

		// 调用外部回调
		if (onFilterChange) {
			onFilterChange(keyStr, value);
		}
	};

	/** 异步生成筛选选项 */
	const generateFilterOptions = async (col: ColumnConfig) => {
		const key = col.key as string;
		if (data.length === 0 || data.length > MAX_FILTER_OPTIONS) return;
		// 如果已经在加载中，则不重复加载
		if (filterOptionsLoading[key]) return;

		filterOptionsLoading[key] = true;
		try {
			// 使用setTimeout将计算放入下一个事件循环，避免阻塞UI
			await new Promise((resolve) => setTimeout(resolve, 0));

			// 优化的去重算法：使用Map单次遍历完成去重，避免多次遍历
			const valueMap = new Map<any, boolean>();
			const options: FilterOption[] = [];

			// 单次遍历完成去重和过滤
			for (let i = 0; i < data.length; i++) {
				const value = data[i][col.key as string];
				// 过滤掉undefined和null，并使用Map去重
				if (value !== undefined && value !== null && !valueMap.has(value)) {
					valueMap.set(value, true);
					options.push({
						label: String(value),
						value
					});
				}
			}

			// 缓存结果
			filterOptionsCache[key] = options;
		} finally {
			// 无论成功失败，都要更新加载状态
			filterOptionsLoading[key] = false;
		}
	};

	/** 切换筛选下拉框 */
	let filterDropdownColumn: ColumnConfig | null = null;
	let filterKeyword = $state<string>(''); //用于搜索下拉框
	const toggleFilterDropdown = (col: ColumnConfig) => {
		if (!col.filterable) return;
		if (filterDropdownVisible === col.key) {
			filterDropdownVisible = null;
			filterDropdownColumn = null;
			document.removeEventListener('mousedown', handleClickOutside);
			window.removeEventListener('keydown', handleEscape);
		} else {
			filterDropdownVisible = col.key;
			filterDropdownColumn = col;
			triggerRects[col.key as string] = getElementRelativePos(triggerRefs[col.key as string]!);
			// 初始化临时筛选值：确保始终是 value 数组
			filterKeyword = '';
			const currentFilter = optionFilterState[col.key as string] || [];
			tempOptionFilters[col.key as string] = Array.isArray(currentFilter)
				? [...currentFilter]
				: currentFilter
					? [currentFilter]
					: [];
			const currentKeywordFilter = keywordFilterState[col.key as string] || [];
			tempKeywordFilters[col.key as string] = Array.isArray(currentKeywordFilter)
				? [...currentKeywordFilter]
				: currentKeywordFilter
					? [currentKeywordFilter]
					: [];
			document.addEventListener('mousedown', handleClickOutside);
			window.addEventListener('keydown', handleEscape);
		}
	};

	const handleClickOutside = (event: MouseEvent) => {
		if (!filterDropdownColumn || !filterDropdownColumn.key) return;
		const popoverRef = popoverSlotRefs?.[filterDropdownColumn.key as string];
		const triggerRef = triggerRefs?.[filterDropdownColumn.key as string];
		if (
			popoverRef && // 弹窗容器存在
			triggerRef && // 触发元素存在
			!popoverRef.contains(event.target as Node) && // 点击不在弹窗内
			!triggerRef.contains(event.target as Node) // 点击不在触发元素内
		) {
			toggleFilterDropdown(filterDropdownColumn);
		}
	};

	const handleEscape = (event: KeyboardEvent) => {
		if (!filterDropdownColumn || !filterDropdownColumn.key) return;
		if (event.key === 'Escape') {
			toggleFilterDropdown(filterDropdownColumn);
		}
	};

	/** 确认筛选 */
	const handleFilterConfirm = (
		col: ColumnConfig,
		valueType: 'option' | 'string' | 'customize',
		customValue?: any
	) => {
		if (valueType === 'customize') {
			const currentFilter = cloneDeep(customValue);
			filter(col.key, currentFilter, valueType);
			toggleFilterDropdown(col);
			return;
		}
		let values: (string | number)[] = [];
		if (valueType === 'option') {
			const currentFilter = tempOptionFilters[col.key as string] || [];
			values = Array.isArray(currentFilter) ? [...currentFilter] : [currentFilter];
		} else if (valueType === 'string') {
			const currentFilter = tempKeywordFilters[col.key as string] || [];
			values = Array.isArray(currentFilter) ? [...currentFilter] : [currentFilter];
		}
		// 确保传递有效的筛选值
		if (values.length > 0) {
			filter(col.key, values, valueType);
		} else {
			// 清除筛选时传递undefined
			filter(col.key, undefined, valueType);
		}
		toggleFilterDropdown(col);
	};

	/** 重置筛选 */
	const handleFilterReset = (col: ColumnConfig) => {
		const key = col.key as string;
		// 清除精确匹配的临时筛选值
		delete tempOptionFilters[key];
		// 清除模糊匹配的临时关键字
		delete tempKeywordFilters[key];
		filter(col.key, undefined, 'delete');
		toggleFilterDropdown(col);
	};
	// 🔥 新增：合计行数据
	let summaryData = $state<Record<string, any>>({});
	let summaryCells = $state<SummaryCell[]>([]); // 用于渲染

	// 🔥 新增：计算合计逻辑
	const calculateSummary = (currentData: any[]) => {
		if (!showSummary) return;

		// 1. 全局自定义方法优先
		if (globalSummaryMethod) {
			summaryData = globalSummaryMethod({ columns, data: currentData });
			// 生成单元格结构（计算宽度合并）
			summaryCells = generateSummaryCells(columns, summaryData, columnWidths);
			return;
		}

		const sums: Record<string, any> = {};

		columns.forEach((col) => {
			const key = col.key as string;

			// A. 静态文本 (summaryText)
			if (col.summaryText !== undefined) {
				sums[key] = col.summaryText;
				return;
			}

			// B. 如果该列被前面的列合并覆盖了（例如 summaryColSpan=0 这种手动配置，虽然我们主要靠 generateSummaryCells 自动处理）
			// 这里主要关注是否开启了 summary
			if (!col.summary) {
				sums[key] = '';
				return;
			}

			// C. 列级自定义方法 (summaryMethod)
			if (col.summaryMethod) {
				sums[key] = col.summaryMethod(currentData);
				return;
			}

			// D. 自动聚合计算
			// 判断聚合类型：如果是 true，默认为 sum
			const type: SummaryType = col.summary === true ? 'sum' : (col.summary as SummaryType);

			const values = currentData.map((item) => item[key]);
			const result = calculateAggregate(values, type);

			if (result !== null) {
				// E. 格式化 (summaryFormatter)
				if (col.summaryFormatter) {
					sums[key] = col.summaryFormatter(result);
				} else {
					sums[key] = result;
				}
			} else {
				sums[key] = '';
			}
		});

		summaryData = sums;
		// 生成渲染用的单元格数据（处理宽度和合并）
		summaryCells = generateSummaryCells(columns, summaryData, columnWidths);
	};
	/** 计算排序和筛选后的数据 */
	let processedData = $state<Array<Record<string, any>>>([]);

	//数据变化手动刷新滚动条校验函数
	let refreshScrollbar: () => void | Promise<void> = $state(() => {});

	const processData = debounce(async (dataToProcess: any[], isInit: boolean = false) => {
		if (isInit) {
			columns.forEach((col) => {
				if (col.filterable && col.dataFilters) {
					generateFilterOptions(col);
				}
			});
		}
		if (dataToProcess.length > MAX_FILTER_OPTIONS) {
			loadingVisible = true;
		}

		await tick();

		setTimeout(async () => {
			await processDataAsync(dataToProcess);
			loadingVisible = false;
			await tick();
			if (refreshScrollbar) {
				await refreshScrollbar(); // 现在可以 await 了，也可以不 await
			}
		}, 16);
	}, 16); // 16ms防抖，避免频繁计算
	const processDataAsync = async (dataToProcess: any[]) => {
		selectedMap.clear();
		isExcludeMode = false;
		version = 0;
		// 快速路径：如果数据为空，直接返回
		if (dataToProcess.length === 0) {
			processedData = [];
			return;
		}
		let result: Array<Record<string, any>> = dataToProcess;
		// 1、先处理数据筛选
		// 预先提取出活跃的筛选条件，避免在循环中重复查找
		const activeOptionFilters = columns.filter(
			(col) => col.filterable && optionFilterState[col.key] && optionFilterState[col.key].length > 0
		);
		const activeKeywordFilters = columns.filter(
			(col) =>
				col.filterable && keywordFilterState[col.key] && keywordFilterState[col.key].length > 0
		);
		// 🔥 新增：找出有自定义筛选值 且 提供了 onFilter 函数的列
		const activeCustomFilters = columns.filter(
			(col) =>
				col.filterable &&
				customFilterState[col.key] !== undefined &&
				typeof col.onFilter === 'function'
		);

		const hasFilters =
			activeOptionFilters.length > 0 ||
			activeKeywordFilters.length > 0 ||
			activeCustomFilters.length > 0;

		// 仅在有筛选时进行单次遍历
		if (hasFilters) {
			result = result.filter((item) => {
				// 检查选项筛选
				for (const col of activeOptionFilters) {
					if (!optionFilterState[col.key].includes(item[col.key])) return false;
				}
				// 检查关键字筛选
				for (const col of activeKeywordFilters) {
					const val = String(item[col.key]).toLowerCase();
					const keywords = keywordFilterState[col.key];
					// 假设 keyword 是 OR 关系，只要匹配一个即可；如果是 AND 改为 every
					if (!keywords.some((k) => val.includes(String(k).trim().toLowerCase()))) {
						return false;
					}
				}
				// 🔥 新增：检查自定义筛选
				for (const col of activeCustomFilters) {
					const filterVal = customFilterState[col.key];
					// 调用父组件提供的 onFilter(筛选值, 行数据)
					// 如果返回 false，则过滤掉该行
					if (!col.onFilter!(filterVal, item)) {
						return false;
					}
				}
				return true;
			});
		}
		//2、在处理排序
		if (sortState.length > 0) {
			// 如果 result 仍然等于 dataToProcess，说明没有经过筛选（filter会生成新数组）。
			// 此时必须进行浅拷贝，否则 sort 会修改原始 data，导致取消排序后无法恢复原样。
			if (result === dataToProcess) {
				result = [...result];
			}
			// 为每个参与排序的列检测数据类型并创建比较器
			const comparators = sortState.map((state) => {
				const keyStr = state.key;
				const sortDir = state.direction;
				let keyType: 'string' | 'number' | 'mixed' = 'mixed';
				const targetCol = columns.find((col) => col.key === keyStr);

				if (targetCol?.keyType) {
					keyType = targetCol.keyType;
				} else if (result.length > 0) {
					// 采样检测类型
					const sampleSize = Math.min(20, result.length);
					let hasString = false;
					let hasNumber = false;
					for (let i = 0; i < sampleSize; i++) {
						const value = result[i][keyStr];
						if (value == null) continue;
						if (typeof value === 'string') hasString = true;
						else if (typeof value === 'number') hasNumber = true;
						if (hasString && hasNumber) break;
					}
					keyType = hasString && hasNumber ? 'mixed' : hasString ? 'string' : 'number';
				}

				// 返回一个包含比较器和key的对象
				return {
					key: keyStr,
					compare: createComparator(sortDir, keyType)
				};
			});

			// 执行排序
			// 注意：由于多列排序比较复杂，这里不再使用 map-sort 优化（Schwartzian transform）
			// 除非在此处构建复杂的复合键，否则直接 sort 的性能通常是可以接受的
			result.sort((a, b) => {
				for (const { key, compare } of comparators) {
					const valA = a[key];
					const valB = b[key];
					// 如果值不相等，直接返回比较结果
					// createComparator 内部通常处理了相等返回 0 的情况，
					// 但我们需要显式判断是否继续比较下一列
					const res = compare(valA, valB);
					if (res !== 0) {
						return res;
					}
					// 如果 res === 0，循环继续，比较下一个排序条件
				}
				return 0; // 所有排序列都相等
			});
		}
		processedData = result;

		// 🔥 计算合计
		if (showSummary) {
			calculateSummary(result);
		}
	};

	// 使用增强版处理函数来响应数据变化
	$effect(() => {
		processData(data, true);
	});

	$effect(() => {
		if (
			showSummary &&
			Object.keys(summaryData).length > 0 &&
			Object.keys(columnWidths).length > 0
		) {
			// 仅重新生成结构，不重新计算数据
			summaryCells = generateSummaryCells(columns, summaryData, columnWidths);
			console.log('执行 generateSummaryCells 生成合计行结构');
		}
	});

	/** 列宽拖动相关逻辑（保留） */

	let draggingCol: string | null = null;
	let currentMinWidth: number = 0; // 默认最小宽（ fallback ）
	let observer: ResizeObserver;

	/** 向上下文暴露方法 */
	setContext(tableContextKey, {
		addColumn,
		removeColumn
		// sort,
		// filter
	} satisfies TableContext);

	// ---------------------------------------------------------
	// 🔥 新增：DPR 监控逻辑
	// ---------------------------------------------------------
	let dpr = $state(1); // 默认为 1，防止 SSR 报错
	let dprMediaQuery: MediaQueryList | null = null;

	const updateDpr = () => {
		const newDpr = window.devicePixelRatio;

		// 只有真正变化时才更新
		if (newDpr !== dpr) {
			dpr = newDpr;
		}

		// 递归绑定：因为 resolution 值变了，旧的 listener 不会再触发，需要重新绑定
		bindDprListener();
	};

	const bindDprListener = () => {
		// 清理旧监听
		if (dprMediaQuery) {
			dprMediaQuery.removeEventListener('change', updateDpr);
		}
		// 创建新监听 (监听当前的精度)
		dprMediaQuery = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
		dprMediaQuery.addEventListener('change', updateDpr);
	};
	onMount(() => {
		portalContainer = ensurePortalContainer('table-popovers-container');
		if (!tableContainerRef) return;
		observer = new ResizeObserver(handleResize);
		observer.observe(tableContainerRef);
		// 🔥 初始化 DPR
		if (typeof window !== 'undefined') {
			dpr = window.devicePixelRatio;
			bindDprListener();
		}
	});

	onDestroy(() => {
		if (tableContainerRef && observer) {
			observer.unobserve(tableContainerRef);
		}
		// 🔥 清理 DPR 监听
		if (dprMediaQuery) {
			dprMediaQuery.removeEventListener('change', updateDpr);
		}
	});

	// 新增：指示线相关变量
	let showGuideLine = $state(false); // 指示线是否显示
	let guideLineLeft = $state(0); // 指示线水平位置（相对于表格容器）
	let guideLineHeight = $state(0); // 指示线高度（与表格一致）
	let currentColOffsetLeft = 0; // 当前拖拽列的左侧偏移量（相对于表格容器内容区）
	let tableContainerLeft = 0;

	let minDragLeft = 0;
	let maxDragLeft = 0;

	// --- 🔥 拖拽逻辑重构 ---
	let resizingGroupKeys: string[] = []; // 当前拖拽列涉及的所有叶子 Key
	let startLeafWidths: Record<string, number> = {}; // 拖拽开始时各叶子的宽度
	let startGroupWidth = 0; // 拖拽开始时分组的总宽

	const startDrag = (e: MouseEvent, col: ColumnConfig) => {
		e.preventDefault();
		e.stopPropagation(); // 防止冒泡
		draggingCol = col.key as string;

		const resizeElement = e.currentTarget as HTMLElement;
		const thElement = resizeElement.closest('.table-th') as HTMLElement; // 获取当前 TH
		if (!tableContainerRef || !thElement) return;

		// 获取涉及的所有叶子节点
		resizingGroupKeys = getLeafKeys(col);

		// 记录初始状态
		startLeafWidths = {};
		startGroupWidth = 0;
		resizingGroupKeys.forEach((key) => {
			const w = getColWidthVal(key);
			startLeafWidths[key] = w;
			startGroupWidth += w;
		});

		// 指示线逻辑
		const tableRect = tableContainerRef.getBoundingClientRect();
		const thRect = thElement.getBoundingClientRect();
		tableContainerLeft = tableRect.left;

		// 指示线位置计算：基于当前被拖拽的 TH 的右边界
		// 注意：如果是分组表头，thRect.right 实际上是最后一列的右边界
		currentColOffsetLeft = thRect.left - tableContainerLeft;
		guideLineLeft = thRect.right - tableContainerLeft;
		guideLineHeight = tableContainerRef.offsetHeight;

		// 最小宽度限制 (简单处理：每列最小 30)
		currentMinWidth = resizingGroupKeys.length * 30;

		showGuideLine = true;
		document.body.style.userSelect = 'none';

		minDragLeft = currentColOffsetLeft + currentMinWidth;
		maxDragLeft = tableContainerRef.clientWidth;

		document.addEventListener('mousemove', handleDrag);
		document.addEventListener('mouseup', stopDrag);
	};

	const handleDrag = throttle((e: MouseEvent) => {
		if (!draggingCol || !tableContainerRef) return;
		// 鼠标X坐标 = 鼠标绝对X - 表格容器左边界 - 容器内边距 + 容器横向滚动量
		const mouseXInContainer = e.clientX - tableContainerLeft;

		guideLineLeft = Math.max(minDragLeft, Math.min(maxDragLeft, mouseXInContainer));
	}, 16);

	const stopDrag = () => {
		if (draggingCol && tableContainerRef) {
			// 计算新总宽
			let newTotalWidth = guideLineLeft - currentColOffsetLeft;
			if (newTotalWidth < currentMinWidth) newTotalWidth = currentMinWidth;

			// 🔥 比例分配逻辑
			// 如果拖的是叶子，resizingGroupKeys 只有一个，ratio = 1 (直接设置)
			// 如果拖的是组，所有子列按比例缩放
			const ratio = newTotalWidth / startGroupWidth;

			const updatedWidths = { ...columnWidths };

			// 必须保留至少1px以防除以0或负数，虽然 minWidth 已控制
			resizingGroupKeys.forEach((key) => {
				const originalW = startLeafWidths[key];
				const newW = Math.floor(originalW * ratio); // 取整避免像素对齐问题

				// 更新 width 配置（用于下次 resize 计算）
				const col = columns.find((c) => c.key === key);
				if (col) col.width = newW;

				updatedWidths[key] = `${newW}px`;
			});

			columnWidths = updatedWidths;

			// 触发重算以处理剩余像素的误差（可选）
			// handleResize();
		}

		showGuideLine = false;
		draggingCol = null;
		resizingGroupKeys = [];
		document.body.style.userSelect = '';
		document.removeEventListener('mousemove', handleDrag);
		document.removeEventListener('mouseup', stopDrag);
	};
	let bodyScrollbarWidth = $state(0);
	let bodyScrollbarHeight = $state(0);
	const gridTemplateColumns = $derived(
		// 1. 处理多选列
		(multiple ? '30px ' : '') +
			// 2. 映射所有列宽
			columns
				.map((col, index) => {
					// 获取当前列宽（带 px 单位的字符串，如 "100px"）
					let width = columnWidths[col.key as string] || 'auto';

					// 🔥 关键逻辑：如果是最后一列
					if (index === columns.length - 1) {
						// 只有当 width 不是 'auto' 时才进行减法运算
						// 如果 width 是 'auto'，CSS calc(auto - 8px) 是无效的
						if (width !== 'auto') {
							// 使用 CSS calc() 函数动态减去滚动条宽度
							// 这里的 bodyScrollbarWidth 是你在 JS 中计算出的变量（如 8 或 17）
							// 如果你不想引入 bodyScrollbarWidth 变量，也可以写死 8px，但建议动态
							return `calc(${width} - ${bodyScrollbarWidth}px)`;
						}
					}

					return width;
				})
				.join(' ')
	);
	let scrollContainerRef: HTMLElement | null = $state(null);
	// 引入版本号，强制更新
	let version = $state(0);
	// 新增：是否为排除模式（true = 全选模式，Map中存储的是被取消勾选的ID）
	let isExcludeMode = $state(false);
	//选中的行索引
	let selectedMap = new Set<string | number>();
	//设置选中的索引
	const handleRowSelect = (row: any, checked: boolean) => {
		const key = row.id;
		if (!key) return;
		if (isExcludeMode) {
			// 【模式2：全选模式】
			// 如果用户勾选(checked=true)，意味着想"选中"它，所以从"排除列表"中移除
			// 如果用户取消勾选(checked=false)，意味着想"排除"它，所以加入"排除列表"
			if (checked) {
				selectedMap.delete(key);
			} else {
				selectedMap.add(key);
			}
		} else {
			// 【模式1：默认模式】
			// 常规逻辑：勾选加ID，取消勾选删ID
			if (checked) {
				selectedMap.add(key);
			} else {
				selectedMap.delete(key);
			}
		}
		version++;
	};
	const handleAllSelect = async (checked: boolean) => {
		if (checked) {
			// 切换到【全选模式】
			isExcludeMode = true;
			// 清空 Map。在排除模式下，Map 为空代表“没有排除任何项”，即“全选”
			selectedMap.clear();
		} else {
			// 切换到【默认模式】
			isExcludeMode = false;
			// 清空 Map。在默认模式下，Map 为空代表“没有选中任何项”
			selectedMap.clear();
		}
		version++;
	};
	// 全选框状态
	let isAllSelected = $derived.by(() => {
		if (version === 0 || processedData.length === 0) return false;

		if (isExcludeMode) {
			// 全选模式下：只有当没有排除项(Map为空)时，才是完全的全选状态
			return selectedMap.size === 0;
		} else {
			// 默认模式下：选中数量等于数据总长
			return selectedMap.size === processedData.length;
		}
	});

	// 半选状态 (Indeterminate)
	let isIndeterminate = $derived.by(() => {
		if (version === 0 || processedData.length === 0) return false;

		if (isExcludeMode) {
			// 全选模式下：如果有排除项，且并没有把所有项都排除
			return selectedMap.size > 0 && selectedMap.size < processedData.length;
		} else {
			// 默认模式下：有选中项，但没选满
			return selectedMap.size > 0 && selectedMap.size < processedData.length;
		}
	});
	const actRowHeight = $derived(rowHeight ? rowHeight : rowHeightMap[size]);
</script>

<!-- 渲染子组件（保持原有逻辑） -->
{@render children?.()}

<!-- 表格容器：宽高默认 100% 继承父容器 -->
<div
	class="table-container"
	class:virtualized
	class:summary={showSummary}
	class:is-horizontal={bodyScrollbarWidth > 0}
	bind:this={tableContainerRef}
	class:small={size === 'sm'}
	class:medium={size === 'md'}
	class:large={size === 'lg'}
	style:--grid-cols={gridTemplateColumns}
	style:--row-height={`${actRowHeight}px`}
	style:--checkbox-color="var(--color-primary-600)"
	style:--dpr={dpr}
>
	<div class="table-content" class:table--border={border}>
		<!-- 🔥 指示器 -->
		{#if showGuideLine}
			<div
				class="resize-guide-line"
				style:left={`${guideLineLeft}px`}
				style:height={`${guideLineHeight}px`}
			></div>
		{/if}

		<div class={`table-thead ${theadClass}`} bind:this={headerScrollContainer}>
			<!-- 1. 多选框列 (作为独立的一列渲染) -->
			{#if multiple}
				<div
					class="check-box-container table-th"
					style:height={`${maxHeaderDepth * actRowHeight}px`}
					style:width="30px"
				>
					<CheckSquare
						{size}
						checked={isAllSelected}
						indeterminate={isIndeterminate}
						onChange={(checked) => handleAllSelect(checked)}
					/>
				</div>
			{/if}
			<!-- 2. 递归渲染表头树 -->
			{#snippet headerNode(cell: HeaderCell)}
				<div class="header-column-container" style:width={`${getGroupWidth(cell.config)}px`}>
					<div
						class="table-th"
						class:is-group={cell.isGroup}
						style:height={`${cell.rowSpan * actRowHeight}px`}
						style:width="100%"
						style:--text-align={cell.config.align}
					>
						<div class="th-content">
							{#if cell.config.slots.header}
								{@render cell.config.slots.header()}
							{:else}
								{cell.config.title}
							{/if}

							<!-- 排序图标 -->
							{#if !cell.isGroup}
								{#if cell.config.sortable}
									{@const currentSort = sortState.find((s) => s.key === cell.key)}
									{@const sortDir = currentSort?.direction}
									{@const sortIndex =
										sortState.length > 1
											? sortState.findIndex((s) => s.key === cell.key) + 1
											: null}
									<div
										class="sort-button"
										onclick={(e) => handleSortClick(e, cell.config)}
										aria-label={sortDir === 'ascend'
											? '降序'
											: sortDir === 'descend'
												? '升序'
												: '排序'}
										role="button"
										tabindex="0"
										onkeydown={() => {}}
									>
										<Icon
											src="symbol/arrow-up-round"
											color={sortDir === 'ascend' ? 'var(--color-primary-600)' : ''}
										/>
										<Icon
											src="symbol/arrow-down-round"
											color={sortDir === 'descend' ? 'var(--color-primary-600)' : ''}
										/>
										{#if sortIndex}
											<span class="sort-index">{sortIndex}</span>
										{/if}
									</div>
								{/if}
							{/if}

							<!-- 筛选图标 -->
							{#if cell.config.filterable}
								<div
									class={`filter-button ${optionFilterState[cell.key as string] ? 'active' : ''}`}
									onclick={() => toggleFilterDropdown(cell.config)}
									aria-label="筛选"
									role="button"
									tabindex="0"
									onkeydown={() => {}}
									style:margin-top="1px"
									bind:this={triggerRefs[cell.key as string]}
									class:is-active={optionFilterState[cell.key as string] ||
										keywordFilterState[cell.key as string] ||
										customFilterState[cell.key as string]}
								>
									<Icon src="office/filter" />
								</div>
							{/if}
						</div>

						<div
							class="resize-handle"
							onmousedown={(e) => startDrag(e, cell.config)}
							role="button"
							tabindex="0"
						></div>

						<!-- 筛选下拉框 -->
						{#if filterDropdownVisible === cell.key && cell.config.filterable}
							<Portal target={portalContainer}>
								<PopoverSlot
									triggerRect={triggerRects[cell.key as string]}
									placement="bottom"
									translateX={-20}
									bind:popoverRef={popoverSlotRefs[cell.key as string]}
									style="padding: 8px;"
								>
									{#if cell.config.slots.filterDropdown}
										{@render cell.config.slots.filterDropdown({
											column: cell.config,
											// 把当前存储的自定义值传出去，以便父组件回显 (例如输入框的值)
											value: customFilterState[cell.key as string],

											// 这里的 val 就是父组件调用 onConfirm 时传进来的自定义对象
											onConfirm: (val) => handleFilterConfirm(cell.config, 'customize', val),
											onReset: () => handleFilterReset(cell.config),
											onClose: () => toggleFilterDropdown(cell.config)
										})}
									{:else if cell.config.dataFilters}
										{#if data.length < MAX_FILTER_OPTIONS + 1}
											{#key cell.key}
												<!-- 使用缓存的筛选选项 -->
												{@const key = cell.key as string}
												{@const options = filterOptionsCache[key] || []}
												<div class="filter-keyword" style:width={size === 'sm' ? '200px' : '240px'}>
													<Input {size} placeholder="搜索选择项" bind:value={filterKeyword} />
												</div>
												<Divider style="dashed" margin="8px" />
												<div class="filter-options">
													<div class="filter-checkbox-select-all">
														<CheckboxSelectAll
															{size}
															label="全选"
															{options}
															bind:modelValue={tempOptionFilters[key]}
														/>
														{#if tempOptionFilters[key].length > 0}
															<Badge
																value={tempOptionFilters[key].length}
																variant="primary"
																{size}
															/>
														{/if}
													</div>
													<div class="filter-checkbox-group-container">
														<CheckboxGroup
															bind:modelValue={tempOptionFilters[key]}
															{size}
															className="filter-checkbox-group"
														>
															{#each options as option}
																<Checkbox
																	value={option.value}
																	label={option.label}
																	className={!option.label
																		.toLowerCase()
																		.includes(filterKeyword.toLowerCase().trim()) &&
																	filterKeyword !== ''
																		? 'filter-checkbox-hidden'
																		: ''}
																/>
															{/each}
														</CheckboxGroup>
													</div>
												</div>
												<Divider style="dashed" margin="8px" />
											{/key}
										{:else}
											<div class="filter-keyword" style:width={size === 'sm' ? '200px' : '240px'}>
												<Input
													{size}
													placeholder="输入关键字筛选"
													bind:value={tempKeywordFilters[cell.key as string][0]}
													onKeydown={(event) => {
														if (event.key === 'Enter') {
															handleFilterConfirm(cell.config, 'string');
														}
													}}
												/>
											</div>
											<Divider style="dashed" margin="8px" />
										{/if}
										<div class="filter-actions">
											<RectButton
												label="重置"
												variant="info"
												type="link"
												onClick={() => handleFilterReset(cell.config)}
												{size}
												style="height: auto;padding:4px 10px;"
											></RectButton>
											<RectButton
												label="筛选"
												variant="primary"
												type="link"
												onClick={() =>
													handleFilterConfirm(
														cell.config,
														data.length < MAX_FILTER_OPTIONS + 1 ? 'option' : 'string'
													)}
												{size}
												style="height: auto;padding:4px 10px;"
											></RectButton>
										</div>
									{:else if cell.config.filters}
										<div class="filter-options">
											<div class="filter-keyword" style:width={size === 'sm' ? '200px' : '240px'}>
												<Input {size} placeholder="搜索选择项" bind:value={filterKeyword} />
											</div>
											<Divider style="dashed" margin="8px" />
											<div class="filter-checkbox-select-all">
												<CheckboxSelectAll
													{size}
													label="全选"
													options={cell.config.filters}
													bind:modelValue={tempOptionFilters[cell.key as string]}
												/>
												{#if tempOptionFilters[cell.key as string].length > 0}
													<Badge
														value={tempOptionFilters[cell.key as string].length}
														variant="primary"
														{size}
													/>
												{/if}
											</div>
											<div class="filter-checkbox-group-container">
												<CheckboxGroup
													bind:modelValue={tempOptionFilters[cell.key as string]}
													{size}
													className="filter-checkbox-group"
												>
													{#each cell.config.filters as option}
														<Checkbox
															value={option.value}
															label={option.label}
															className={!option.label
																.toLowerCase()
																.includes(filterKeyword.toLowerCase().trim()) &&
															filterKeyword !== ''
																? 'filter-checkbox-hidden'
																: ''}
														/>
													{/each}
												</CheckboxGroup>
											</div>
										</div>
										<Divider style="dashed" margin="8px" />
										<div class="filter-actions">
											<RectButton
												label="重置"
												variant="info"
												type="link"
												onClick={() => handleFilterReset(cell.config)}
												{size}
												style="height: auto;padding:4px 10px;"
											></RectButton>
											<RectButton
												label="筛选"
												variant="primary"
												type="link"
												onClick={() => handleFilterConfirm(cell.config, 'option')}
												{size}
												style="height: auto;padding:4px 10px;"
											></RectButton>
										</div>
									{:else}
										<div class="filter-keyword" style:width={size === 'sm' ? '200px' : '240px'}>
											<Input
												{size}
												placeholder="输入关键字筛选"
												bind:value={tempKeywordFilters[cell.key as string][0]}
												onKeydown={(event) => {
													if (event.key === 'Enter') {
														handleFilterConfirm(cell.config, 'string');
													}
												}}
											/>
										</div>
										<Divider style="dashed" margin="8px" />
										<div class="filter-actions">
											<RectButton
												label="重置"
												variant="info"
												type="link"
												onClick={() => handleFilterReset(cell.config)}
												{size}
												style="height: auto;padding:4px 10px;"
											></RectButton>
											<RectButton
												label="筛选"
												variant="primary"
												type="link"
												onClick={() => handleFilterConfirm(cell.config, 'string')}
												{size}
												style="height: auto;padding:4px 10px;"
											></RectButton>
										</div>
									{/if}
								</PopoverSlot>
							</Portal>
						{/if}
					</div>
					<!-- B. 子节点容器 (递归入口) -->
					{#if cell.children && cell.children.length > 0}
						<div class="header-children-row">
							{#each cell.children as child (child.key)}
								{@render headerNode(child)}
							{/each}
						</div>
					{/if}
				</div>
			{/snippet}
			<!-- 循环根节点调用 snippet -->
			{#each headerTree as cell (cell.key)}
				{@render headerNode(cell)}
			{/each}
		</div>

		{#if virtualized}
			{#if isLoading || loadingVisible}
				<div class="loading" style:top={`${maxHeaderDepth * actRowHeight - 2}px`}>
					<LoadingBar />
				</div>
			{/if}
			{#if processedData.length > 0}
				<VirtualScroll
					data={processedData}
					itemHeight={actRowHeight}
					bufferSize={10}
					onScrollPositionChange={handleTbodyScroll}
					styles="flex:1"
					scrollTypeX="auto"
					scrollTypeY="auto"
					bind:scrollContainerRef
					onScrollbarChange={(
						hasVerticalScroll: boolean,
						scrollbarWidth: number,
						hasHorizontalScroll: boolean,
						scrollbarHeight: number
					) => {
						bodyScrollbarWidth = hasVerticalScroll ? 10 : 0;
						bodyScrollbarHeight = hasHorizontalScroll ? 10 : 0;
					}}
				>
					{#snippet children({ visibleData })}
						<!-- 表体：虚拟滚动，使用简化的grid布局层级 -->
						<div class={`table-tbody virtual-table-tbody ${tbodyClass}}`}>
							<!-- 性能优化：使用优化的key生成函数，并预先计算索引 -->
							<!-- 正确使用Svelte each循环的key语法 -->
							{#each visibleData as row, index (row.id)}
								<!-- 计算原始索引（关键！） -->
								<div class={`table-tr ${stripe && index % 2 === 1 ? 'table-tr--stripe' : ''}`}>
									{#if multiple}
										<div class="check-box-container">
											<CheckSquare
												{size}
												checked={version > 0 &&
													(isExcludeMode ? !selectedMap.has(row.id) : selectedMap.has(row.id))}
												onChange={(checked) => handleRowSelect(row, checked)}
											/>
										</div>
									{/if}
									<!-- 性能优化：减少嵌套循环中的属性访问 -->
									{#each columns as col}
										<div class="table-td" style:--text-align={col.align}>
											{#if col.slots.cell}
												{@render col.slots.cell({ row, index: index, column: col })}
											{:else}
												{row[col.key]}
											{/if}
										</div>
									{/each}
								</div>
							{/each}
						</div>
					{/snippet}
				</VirtualScroll>
			{/if}
		{:else}
			<!-- 原始滚动实现 -->
			<Scrollbar
				scrollWidth={10}
				onScrollPositionChange={handleTbodyScroll}
				style={`min-height: 0;padding: 0;flex:1;`}
				scrollTypeX="auto"
				scrollTypeY="auto"
				bind:checkScrollbar={refreshScrollbar}
				bind:scrollContainerRef
				onScrollbarChange={(
					hasVerticalScroll: boolean,
					scrollbarWidth: number,
					hasHorizontalScroll: boolean,
					scrollbarHeight: number
				) => {
					bodyScrollbarWidth = hasVerticalScroll ? 10 : 0;
					bodyScrollbarHeight = hasHorizontalScroll ? 10 : 0;
				}}
			>
				<!-- 表体：自然滚动，使用简化的grid布局层级 -->
				<div class={`table-tbody ${tbodyClass}`} style:will-change="transform">
					{#each processedData as row, rowIndex (row.id || rowIndex)}
						<div
							class={`table-tr ${rowClass(row, rowIndex)} ${stripe && rowIndex % 2 === 1 ? 'table-tr--stripe' : ''}`}
						>
							{#if multiple}
								<div class="check-box-container">
									<CheckSquare
										{size}
										checked={version > 0 &&
											(isExcludeMode ? !selectedMap.has(row.id) : selectedMap.has(row.id))}
										onChange={(checked) => handleRowSelect(row, checked)}
									/>
								</div>
							{/if}
							{#each columns as col (col.key)}
								<div class="table-td" style:--text-align={col.align}>
									{#if col.slots.cell}
										{@render col.slots.cell({ row, index: rowIndex, column: col })}
									{:else}
										{row[col.key]}
									{/if}
								</div>
							{/each}
						</div>
					{/each}
				</div>
			</Scrollbar>
		{/if}
		{#if showSummary}
			<div
				class="footer-container"
				bind:this={footerScrollContainer}
				style:height={`${actRowHeight}px`}
			>
				<div class="table-tfoot">
					<!-- 多选框占位 -->
					{#if multiple}
						<div class="check-box-container table-td" style:width="30px"></div>
					{/if}

					{#each summaryCells as cell (cell.key)}
						{#if !cell.skip}
							<!-- 跳过被合并的单元格 -->
							<div
								class="table-td"
								style:--text-align={cell.align}
								style:width={`${cell.width}px`}
								class:is-merged={cell.colSpan > 1}
							>
								{cell.value}
							</div>
						{/if}
					{/each}
				</div>
			</div>
		{/if}
	</div>
</div>

<style lang="scss">
	@use './styles/table.scss';
</style>